#include <my_head.h>

typedef struct _Msg{
    const char *src_file;   // 源文件名
    const char *dest_file;  // 目标文件名
    int offset;             // 起点
    int cp_len;             // 要拷贝的字节数
}msg_t;

// 线程处理函数 -- 拷贝文件
void *task_func(void *arg){
    // 接收参数
    msg_t msg = *(msg_t *)arg;
    // 打开源文件和目标文件
    int fd_src = open(msg.src_file, O_RDONLY);
    if(-1 == fd_src)
        ERR_LOG("open error");
    int fd_dest = open(msg.dest_file, O_WRONLY);
    if(-1 == fd_dest)
        ERR_LOG("open error");
    // 定位光标
    lseek(fd_src, msg.offset, SEEK_SET);
    lseek(fd_dest, msg.offset, SEEK_SET);
    // 拷贝
    char buff[10];
    int ret;
    int count = 0;
    while(0 < (ret = read(fd_src, buff, sizeof(buff)))){
        count += ret;
        if(count >= msg.cp_len){
            write(fd_dest, buff, msg.cp_len-(count-ret));
            break;
        }
        write(fd_dest, buff, ret);
    }
    // 关闭文件
    close(fd_src);
    close(fd_dest);
}

// 获取源文件大小 并 创建目标文件
int get_srclen_and_create_dest(const char *src_file, const char *dest_file){
    int fd = 0;
    if(-1 == (fd = open(src_file, O_RDONLY)))
        ERR_LOG("open error");
    int length = lseek(fd, 0, SEEK_END);
    close(fd);
    if(-1 == (fd = open(dest_file, O_WRONLY|O_CREAT|O_TRUNC, 0664)))
        ERR_LOG("open error");
    close(fd);
    return length;
}

int main(int argc, const char *argv[]){
    if(4 != argc){
        printf("Usage : %s src_file dest_file thread_count\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    // 获取线程数量
    int thread_count = atoi(argv[3]);
    // 根据线程数量分配空间存放线程的tid
    pthread_t *tid = (pthread_t *)malloc(sizeof(pthread_t) * thread_count);
    if(NULL == tid){
        printf("内存分配失败\n");
        exit(EXIT_FAILURE);
    }
    // 获取源文件大小 并 创建目标文件
    int length = get_srclen_and_create_dest(argv[1], argv[2]);
    // 分配空间用来存放每个线程的 任务量（给每个线程传的参数）
    msg_t *msg = (msg_t *)malloc(sizeof(msg_t) * thread_count);
    if(NULL == msg){
        printf("内存分配失败\n");
        exit(EXIT_FAILURE);
    }
    // 计算每个线程的任务量
    int one_thread_cp_len = length / thread_count;
    // 创建线程
    int ret;
    for(int i = 0; i < thread_count; i++){
        // 给每个线程分配任务量
        msg[i].src_file = argv[1];
        msg[i].dest_file = argv[2];
        msg[i].offset = i * one_thread_cp_len;
        if(i < thread_count-1){
            msg[i].cp_len = one_thread_cp_len;
        }else{
            // 最后一个线程应该把剩下的字节数全拷贝
            msg[i].cp_len = length - ((thread_count-1)*one_thread_cp_len);
        }
        if(0 != (ret = pthread_create(tid+i , NULL, task_func, msg+i))){
            printf("pthread_create error : [%d] [%s]\n", ret, strerror(ret));
            exit(EXIT_FAILURE);
        }
    }
    // 阻塞等待子线程们结束 为他们回收资源
    for(int i = 0; i < thread_count; i++){
        pthread_join(tid[i], NULL);
    }
    // 释放空间
    free(tid);
    free(msg);
    return 0;
}